// 堆结构和堆排序，acm练习风格
// 测试链接 : https://www.nowcoder.com/practice/ed8308a5f0f744fc936bdba78c15f810
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率较高的写法
// 提交以下的code，可以直接通过

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 501;
int arr[MAXN];
int n;

int read()
{
    char ch = getchar();
    int x = 0, f = 1;
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = 10 * x + ch - '0';
        ch = getchar();
    }
    return f * x;
}

// i位置的数，向上调整大根堆
void heapInsert(int i)
{
    while(arr[i] > arr[(i - 1) / 2])
    {
        swap(arr[i], arr[(i - 1) / 2]);
        i = (i - 1) / 2;
    }
}

// i位置的数，向下调整大根堆
// 当前堆的大小为sz
void heapify(int i, int sz)
{
    int l = 2 * i + 1;
    while(l < sz)
    {
        int best = l + 1 < sz && arr[l + 1] > arr[l] ? l + 1 : l;
        best = arr[best] > arr[i] ? best : i;
        if(best == i) break;
        swap(arr[i], arr[best]);
        i = best;
        l = 2 * i + 1;
    }
}

// 从顶到底建立大根堆，O(n * logn)
// 依次弹出堆内最大值并排好序，O(n * logn)
// 整体时间复杂度O(n * logn)
void heapSort1()
{
    for(int i = 0; i < n; ++i) 
    {
        heapInsert(i);
    }

    int sz = n;
    while(sz > 1)
    {
        swap(arr[0], arr[--sz]);
        heapify(0, sz);
    }
}

// 从底到顶建立大根堆，O(n)
// 依次弹出堆内最大值并排好序，O(n * logn)
// 整体时间复杂度O(n * logn)
void heapSort2()
{
    // 这里将 i 改成 (n - 1 - 1) / 2
    // 从第一个非叶子节点开始向下调整
    // 因为叶子节点也已经不能往下调整了
    for(int i = n - 1; i >= 0; --i)
    {
        heapify(i, n);
    }

    int sz = n;
    while(sz > 1)
    {
        swap(arr[0], arr[--sz]);
        heapify(0, sz);
    }
}

int main()
{
    n = read();
    for(int i = 0; i < n; ++i) arr[i] = read();
    // heapSort1为从顶到底建堆然后排序
    // heapSort2为从底到顶建堆然后排序
    // 用哪个都可以
    // heapSort1();
    heapSort2();
    printf("%d", arr[0]);
    for(int i = 1; i < n; ++i)
    {
        printf(" %d", arr[i]);
    }
    printf("\n");

    return 0;
}